<?php

namespace UtilityKit\Utility;

use Contract\Exceptions\ValidationException;
use DateInterval;
use DateTime;
use DateTimeZone;

class DateTimeUtility
{
    /**
     * @param string $time
     * @param string $format
     * @param string $timezone
     * @return DateTime
     * @throws ValidationException
     */
    public static function getDatetime(string $time, string $format, string $timezone = 'Asia/Shanghai'): DateTime
    {
        $datetimeZone = new DateTimeZone($timezone);
        if ($datetimeZone === false) {
            throw new ValidationException(sprintf('时区格式错误 timezone: %s', $timezone));
        }
        $datetime = DateTime::createFromFormat($format, $time, $datetimeZone);
        if ($datetime === false) {
            throw new ValidationException(sprintf('时间格式错误 format: %s, time: %s', $format, $time));
        }
        return $datetime;
    }

    /**
     * @param string $startTime
     * @param string $endTime
     * @param string $format
     * @return array
     * @throws ValidationException
     */
    public static function getMomDateInterval(string $startTime, string $endTime, string $format): array
    {
        $startDatetime = static::getDatetime($startTime, $format);
        $endDatetime = static::getDatetime($endTime, $format);
        $dateInterval = $endDatetime->diff($startDatetime, true);
        $momEndTime = $startDatetime->sub(new DateInterval('P1D'))->format($format);
        $momStartTime = $startDatetime->sub($dateInterval)->format($format);
        return [$momStartTime, $momEndTime];
    }

    /**
     * @param string $startTime
     * @param string $endTime
     * @param string $format
     * @return array
     * @throws ValidationException
     */
    public static function getYoyDateInterval(string $startTime, string $endTime, string $format): array
    {
        $startDatetime = static::getDatetime($startTime, $format);
        $endDatetime = static::getDatetime($endTime, $format);
        $dateInterval = $endDatetime->diff($startDatetime, true);
        $yoyEndTime = $endDatetime->sub(new DateInterval('P1Y'))->format($format);
        $yoyStartTime = $endDatetime->sub($dateInterval)->format($format);
        return [$yoyStartTime, $yoyEndTime];
    }

    public static function floatMicroTime(): float
    {
        list($usec, $sec) = explode(" ", microtime());
        return ((float)$usec + (float)$sec);
    }

    public static function milliSecond(): int
    {
        $floatMicroTime = self::floatMicroTime();
        return intval($floatMicroTime * 1000);
    }

    public static function microSecond(): int
    {
        $floatMicroTime = self::floatMicroTime();
        return intval($floatMicroTime * 1000000);
    }
}